from telnetlib import SB
from typing import List
from utils import matrix_inv,get_aver,matrix_mul,matrix_sub,matrix_add,matrix_tran,get_pc


def get_sb_sw(s: List[List]) -> tuple:
    '''
    求样本集的Sb矩阵和Sw矩阵
    输入 样本分类集合 形如 [ [[1,1],[2,2]], [[3,3]]  ]
    返回 Sb, Sw
    '''

    # 得到样本集w [ [[1,1],[2,2]], [[3,3]]  ] -> [ [1,1], [2,2], [3,3] ]
    w = []
    for ss in s:
        w += [ sss for sss in ss]

    # 计算总体均值和各类样本均值
    u = get_aver(w)
    ui = [get_aver(wi) for wi in s]

    # 计算Sb矩阵
    Sb = matrix_mul(len(s[0]), matrix_mul(matrix_sub(ui[0],u), matrix_tran(matrix_sub(ui[0],u)) ))
    for i,uii in enumerate(ui[1:]):
        Sb = matrix_add(Sb, matrix_mul(len(s[i+1]), matrix_mul(matrix_sub(uii,u), matrix_tran(matrix_sub(uii,u)))))

    # 计算Sw矩阵
    Sw = matrix_mul( matrix_sub(s[0][0], ui[0]), matrix_tran(matrix_sub(s[0][0], ui[0])) ) 
    for xi in s[0][1:]:
        Sw = matrix_add(Sw, matrix_mul( matrix_sub(xi, ui[0]), matrix_tran(matrix_sub(xi, ui[0]))))
    for i,x in enumerate(s[1:]):
        for xi in x:
            Sw = matrix_add(Sw, matrix_mul( matrix_sub(xi, ui[i+1]), matrix_tran(matrix_sub(xi, ui[i+1]))) )

    return Sb, Sw

def FDA(s: List[List]) -> tuple:
    '''
    基于Fisher准则的可分性分析算法
    输入 样本分类集合 形如 [ [[1,1],[2,2]], [[3,3]]  ]
    返回 降维结果 主分量e1
    '''

    Sb, Sw = get_sb_sw(s)

    w = []
    for ss in s:
        w += [ sss for sss in ss]
    
    pc = get_pc(matrix_mul(matrix_inv(Sw),Sb))

    return [ matrix_mul([v],pc)[0] for v in w], pc



# for debug
# w1 = [ [1,3], [1,4], [3,0], [3,1] ]
# w2 = [ [3,6], [3,7], [5,5], [5,4] ]
# w3 = [ [8,5], [9,9], [9,5], [10,9] ]


# fda = FDA([w1,w2,w3])
# print(fda)


# u = get_aver(w1 + w2 + w3)
# u1 = get_aver(w1)
# u2 = get_aver(w2)
# u3 = get_aver(w3)

# print(u, u1, u2, u3)

